import time
import _thread

'''
    异步yield生成器注解升级版
    注意: 不要在Sublime直接运行, 会看不到多线程执行结果, 得去cmd执行或用SublimeREPL

    yield的核心:
            next(gen)               # 开始运行生成器里面的代码并卡在yield
            gen.send(result)        # 卡在的地方继续运行并在yield前插入result值
'''

gen = None   # 全局生成器

# 装饰器: 将生成器封装得更像一个函数
def gen_coroutine(f):
    def wrapper(*args, **kwargs):
        global gen
        gen = f()
        next(gen)
    return wrapper

# 取这个名字很耗时
def get_name():
    time.sleep(5)
    return 'xiaoming'

# 这里我们假设这次long_io的目的是去获取一个名字
def long_io():
    def fun():
        global gen
        print("开始执行IO操作")
        io_result = get_name()                  # 这个io_result就是异步的结果, 咱折腾那么久其实就是为了得到它
        print("完成IO操作，并send结果唤醒挂起程序继续执行")
        try:
            gen.send(io_result)                 # 归还控制权, 继续执行req_a()中的ret=yield long_io() ==> ret=io_result
        except StopIteration:                   # 捕获生成器完成迭代，防止程序退出
            pass
    _thread.start_new_thread(fun, ())           


@gen_coroutine
def req_a():
    print('开始处理请求req_a')
    ret = yield long_io()
    print("The name is : %s" % ret)
    print('离开处理请求req_a')


def req_b():
    print('开始处理请求req_b')
    time.sleep(2)                               # 添加此句来突出显示程序执行的过程
    print('完成处理请求req_b')


def main():
    req_a()
    req_b()
    while 1:
        pass

if __name__ == "__main__":
    main()
